home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / programr / ole2book.zip / CHAP07.ZIP / CHAP07 / PATRON / PAGEWIN.CPP < prev    next >
C/C++ Source or Header  |  1993-06-17  |  22KB  |  828 lines

  1. /*
  2.  * PAGEWIN.CPP
  3.  * Modifications for Chapter 7
  4.  *
  5.  * Window procedure for the Pages window and support functions.  This
  6.  * window manages its own scrollbars and viewport and provides
  7.  * printing capabilities as well.  The public CPages::Print lives here.
  8.  *
  9.  * Copyright (c)1993 Microsoft Corporation, All Rights Reserved
  10.  *
  11.  * Kraig Brockschmidt, Software Design Engineer
  12.  * Microsoft Systems Developer Relations
  13.  *
  14.  * Internet  :  kraigb@microsoft.com
  15.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  16.  */
  17.  
  18.  
  19.  
  20. #include "patron.h"
  21.  
  22.  
  23. extern HWND g_hDlgPrint;
  24. extern BOOL g_fCancelPrint;
  25.  
  26.  
  27. /*
  28.  * PagesWndProc
  29.  *
  30.  * Purpose:
  31.  *  Window procedure for the Pages window.
  32.  */
  33.  
  34. LRESULT __export FAR PASCAL PagesWndProc(HWND hWnd, UINT iMsg
  35.     , WPARAM wParam, LPARAM lParam)
  36.     {
  37.     LPCPages        ppg;
  38.     PAINTSTRUCT     ps;
  39.     HDC             hDC;
  40.     int             iPos, iTmp;
  41.     int             iMin, iMax;
  42.     UINT            idScroll;
  43.     //CHAPTER7MOD
  44.     BOOL            fDirty=FALSE;
  45.     //End CHAPTER7MOD
  46.  
  47.     ppg=(LPCPages)GetWindowLong(hWnd, PAGEWL_STRUCTURE);
  48.  
  49.     switch (iMsg)
  50.         {
  51.         case WM_CREATE:
  52.             ppg=(LPCPages)((LPCREATESTRUCT)lParam)->lpCreateParams;
  53.             SetWindowLong(hWnd, PAGEWL_STRUCTURE, (LONG)ppg);
  54.  
  55.             ppg->m_hWnd=hWnd;
  56.             break;
  57.  
  58.  
  59.         case WM_PAINT:
  60.             hDC=BeginPaint(hWnd, &ps);
  61.  
  62.             //Draw only if we have a page to show.
  63.             if (0!=ppg->m_cPages)
  64.                 ppg->Draw(hDC, FALSE, FALSE);
  65.  
  66.             EndPaint(hWnd, &ps);
  67.             break;
  68.  
  69.  
  70.         case WM_HSCROLL:
  71.         case WM_VSCROLL:
  72.             idScroll=(WM_HSCROLL==iMsg) ? SB_HORZ : SB_VERT;
  73.  
  74.             iPos=GetScrollPos(hWnd, idScroll);
  75.             iTmp=iPos;
  76.             GetScrollRange(hWnd, idScroll, &iMin, &iMax);
  77.  
  78.             switch (wParam)
  79.                 {
  80.                 case SB_LINEUP:     iPos -= 20;  break;
  81.                 case SB_PAGEUP:     iPos -=100;  break;
  82.                 case SB_LINEDOWN:   iPos += 20;  break;
  83.                 case SB_PAGEDOWN:   iPos +=100;  break;
  84.  
  85.                 case SB_THUMBPOSITION:
  86.                     iPos=ScrollThumbPosition(wParam, lParam);
  87.                     break;
  88.  
  89.                 //We don't want scrolling on this message.
  90.                 case SB_THUMBTRACK:
  91.                     return 0L;
  92.                 }
  93.  
  94.             iPos=max(iMin, min(iPos, iMax));
  95.  
  96.             if (iPos!=iTmp)
  97.                 {
  98.                 //Set the new position and scroll the window as necessary.
  99.                 SetScrollPos(hWnd, idScroll, iPos, TRUE);
  100.  
  101.                 if (SB_HORZ==idScroll)
  102.                     {
  103.                     ppg->m_xPos=iPos;
  104.                     ScrollWindow(hWnd, iTmp-iPos, 0, NULL, NULL);
  105.                     }
  106.                 else
  107.                     {
  108.                     ppg->m_yPos=iPos;
  109.                     ScrollWindow(hWnd, 0, iTmp-iPos, NULL, NULL);
  110.                     }
  111.                 }
  112.  
  113.             break;
  114.  
  115.         //CHAPTER7MOD
  116.         case WM_LBUTTONDOWN:
  117.             if (NULL==ppg->m_pPageCur)
  118.                 break;
  119.  
  120.             fDirty=ppg->m_pPageCur->OnLeftDown(wParam
  121.                 , LOWORD(lParam), HIWORD(lParam));
  122.             break;
  123.  
  124.         case WM_LBUTTONUP:
  125.             if (NULL==ppg->m_pPageCur)
  126.                 break;
  127.  
  128.             fDirty=ppg->m_pPageCur->OnLeftUp(wParam
  129.                 , LOWORD(lParam), HIWORD(lParam));
  130.             break;
  131.  
  132.         case WM_LBUTTONDBLCLK:
  133.             if (NULL==ppg->m_pPageCur)
  134.                 break;
  135.  
  136.             fDirty=ppg->m_pPageCur->OnLeftDoubleClick(wParam, LOWORD(lParam)
  137.                 , HIWORD(lParam));
  138.             break;
  139.  
  140.         case WM_MOUSEMOVE:
  141.             if (NULL==ppg->m_pPageCur)
  142.                 break;
  143.  
  144.             ppg->m_pPageCur->OnMouseMove(wParam, LOWORD(lParam)
  145.                 , HIWORD(lParam));
  146.             break;
  147.  
  148.         case WM_NCHITTEST:
  149.             if (NULL!=ppg->m_pPageCur)
  150.                 {
  151.                 //This just saves information in the page for OnSetCursor
  152.                 ppg->m_pPageCur->OnNCHitTest(LOWORD(lParam)
  153.                     , HIWORD(lParam));
  154.                 }
  155.  
  156.             return DefWindowProc(hWnd, iMsg, wParam, lParam);
  157.  
  158.         case WM_SETCURSOR:
  159.             if (NULL!=ppg->m_pPageCur)
  160.                 {
  161.                 if (ppg->m_pPageCur->OnSetCursor(LOWORD(lParam)))
  162.                     break;
  163.                 }
  164.  
  165.             return DefWindowProc(hWnd, iMsg, wParam, lParam);
  166.  
  167.         //End CHAPTER7MOD
  168.  
  169.         default:
  170.             return DefWindowProc(hWnd, iMsg, wParam, lParam);
  171.         }
  172.  
  173.     //CHAPTER7MOD
  174.     ppg->m_fDirty |= fDirty;
  175.     //End CHAPTER7MOD
  176.     return 0L;
  177.     }
  178.  
  179.  
  180.  
  181. //CHAPTER7MOD
  182. //This is now a global function.
  183.  
  184. /*
  185.  * RectConvertMappings
  186.  *
  187.  * Purpose:
  188.  *  Converts the contents of a rectangle from device to logical
  189.  *  coordinates where the hDC defines the logical coordinates.
  190.  *
  191.  * Parameters:
  192.  *  pRect           LPRECT containing the rectangle to convert.
  193.  *  hDC             HDC describing the logical coordinate system.
  194.  *                  if NULL, uses a screen DC in MM_LOMETRIC.
  195.  *  fToDevice       BOOL TRUE to convert from uConv to device,
  196.  *                  FALSE to convert device to uConv.
  197.  *
  198.  * Return Value:
  199.  *  None
  200.  */
  201.  
  202. void RectConvertMappings(LPRECT pRect, HDC hDC, BOOL fToDevice)
  203.     {
  204.     POINT   rgpt[2];
  205.     BOOL    fSysDC=FALSE;
  206.  
  207.     if (NULL==pRect)
  208.         return;
  209.  
  210.     rgpt[0].x=pRect->left;
  211.     rgpt[0].y=pRect->top;
  212.     rgpt[1].x=pRect->right;
  213.     rgpt[1].y=pRect->bottom;
  214.  
  215.     if (NULL==hDC)
  216.         {
  217.         hDC=GetDC(NULL);
  218.         SetMapMode(hDC, MM_LOMETRIC);
  219.         fSysDC=TRUE;
  220.         }
  221.  
  222.     if (fToDevice)
  223.         LPtoDP(hDC, rgpt, 2);
  224.     else
  225.         DPtoLP(hDC, rgpt, 2);
  226.  
  227.     if (fSysDC)
  228.         ReleaseDC(NULL, hDC);
  229.  
  230.     pRect->left=rgpt[0].x;
  231.     pRect->top=rgpt[0].y;
  232.     pRect->right=rgpt[1].x;
  233.     pRect->bottom=rgpt[1].y;
  234.  
  235.     return;
  236.     }
  237. //End CHAPTER7MOD
  238.  
  239.  
  240.  
  241.  
  242.  
  243.  
  244. /*
  245.  * CPages::Draw
  246.  *
  247.  * Purpose:
  248.  *  Paints the current page in the pages window.
  249.  *
  250.  * Parameters:
  251.  *  hDC             HDC to draw on, could be a metafile or printer DC or
  252.  *                  any other type of DC.
  253.  *  fNoColor        BOOL indicating if we should use screen colors or
  254.  *                  printer colos (B&W).  Objects are printed as-is, however.
  255.  *                  This is TRUE for printer DCs or print preview.
  256.  *  fPrinter        BOOL indicating if this is a printer DC in which case
  257.  *                  we eliminate some of the fancy drawing, like shadows on
  258.  *                  the page and so forth.
  259.  *
  260.  * Return Value:
  261.  *  None
  262.  */
  263.  
  264. void CPages::Draw(HDC hDC, BOOL fNoColor, BOOL fPrinter)
  265.     {
  266.     RECT            rc, rcT;
  267.     UINT            uMM;
  268.     HPEN            hPen;
  269.     HBRUSH          hBrush;
  270.     HGDIOBJ         hObj1, hObj2;
  271.     COLORREF        cr;
  272.     char            szTemp[20];
  273.     UINT            cch;
  274.     DWORD           dwExt;
  275.     //CHAPTER7MOD
  276.     LPPAGE          pPage;
  277.     RECT            rcPos;
  278.     //End CHAPTER7MOD
  279.  
  280.     //Make sure the DC is in LOMETRIC
  281.     uMM=SetMapMode(hDC, MM_LOMETRIC);
  282.  
  283.     if (!fPrinter)
  284.         {
  285.         /*
  286.          * We maintain a 6mm border around the page on the screen besides
  287.          * 12.7mm margins.  We also have to account for the scroll position
  288.          * with m_*Pos which are in pixels so we have to convert them.
  289.          */
  290.         SetRect(&rcPos, m_xPos, m_yPos, 0, 0);
  291.         RectConvertMappings(&rcPos, hDC, FALSE);
  292.  
  293.         rc.left  = LOMETRIC_BORDER-rcPos.left;
  294.         rc.top   =-LOMETRIC_BORDER-rcPos.top;
  295.         }
  296.     else
  297.         {
  298.         /*
  299.          * We define the corner of the printed paper at a negative
  300.          * offset so rc.right and rc.bottom come out right below.
  301.          */
  302.         SetRect(&rc, -(int)m_xMarginLeft, m_yMarginTop, 0, 0);
  303.         }
  304.  
  305.     rc.right =rc.left+(UINT)m_cx+(UINT)(m_xMarginLeft+m_xMarginRight);
  306.     rc.bottom=rc.top -(UINT)m_cy-(UINT)(m_yMarginTop+m_yMarginBottom);
  307.  
  308.     //Draw a rectangle filled with the window color to show the page.
  309.     if (!fPrinter)
  310.         {
  311.         if (fNoColor)
  312.             {
  313.             //Black frame, white box for printed colors.
  314.             hPen  =CreatePen(PS_SOLID, 0, RGB(0,0,0));
  315.             hBrush=CreateSolidBrush(RGB(255, 255, 255));
  316.             }
  317.         else
  318.             {
  319.             //Normal colors on display
  320.             hPen  =CreatePen(PS_SOLID, 0, GetSysColor(COLOR_WINDOWFRAME));
  321.             hBrush=CreateSolidBrush(GetSysColor(COLOR_WINDOW));
  322.             }
  323.  
  324.         hObj1=SelectObject(hDC, hPen);
  325.         hObj2=SelectObject(hDC, hBrush);
  326.  
  327.         //Paper boundary
  328.         Rectangle(hDC, rc.left, rc.top, rc.right, rc.bottom+1);
  329.  
  330.         /*
  331.          * Draw a shadow on the *visual* bottom and right edges .5mm wide.
  332.          * If the button shadow color and workspace colors match, then
  333.          * use black.  We always use black when printing as well.
  334.          */
  335.         if (fNoColor)
  336.             cr=RGB(0,0,0);
  337.         else
  338.             {
  339.             cr=GetSysColor(COLOR_BTNSHADOW);
  340.  
  341.             if (GetSysColor(COLOR_APPWORKSPACE)==cr)
  342.                 cr=RGB(0,0,0);
  343.             }
  344.  
  345.         cr=SetBkColor(hDC, cr);
  346.         SetRect(&rcT, rc.left+5, rc.bottom, rc.right+5, rc.bottom-5);
  347.         ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &rcT, NULL, 0, NULL);
  348.  
  349.         SetRect(&rcT, rc.right, rc.top-5, rc.right+5, rc.bottom-5);
  350.         ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &rcT, NULL, 0, NULL);
  351.         SetBkColor(hDC, cr);
  352.  
  353.         SelectObject(hDC, hObj1);
  354.         SelectObject(hDC, hObj2);
  355.         DeleteObject(hBrush);
  356.         DeleteObject(hPen);
  357.         }
  358.  
  359.     //Write the page number in the lower left corner
  360.     if (!fNoColor)
  361.         {
  362.         SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
  363.         SetBkColor(hDC, GetSysColor(COLOR_WINDOW));
  364.         }
  365.  
  366.     //Write the page number in our page font.
  367.     cch=wsprintf(szTemp, "Page %d", m_iPageCur+1);
  368.  
  369.     hObj1=SelectObject(hDC, m_hFont);
  370.     dwExt=GetTextExtent(hDC, szTemp, cch);
  371.  
  372.     TextOut(hDC, rc.left+m_xMarginLeft
  373.         , rc.bottom+m_yMarginBottom+HIWORD(dwExt), szTemp, cch);
  374.  
  375.     SelectObject(hDC, hObj1);
  376.  
  377.     //Rectangle to show border.
  378.     MoveTo(hDC, rc.left+m_xMarginLeft,   rc.top-m_yMarginTop);
  379.     LineTo(hDC, rc.left+m_xMarginLeft,   rc.bottom+m_yMarginBottom);
  380.     LineTo(hDC, rc.right-m_xMarginRight, rc.bottom+m_yMarginBottom);
  381.     LineTo(hDC, rc.right-m_xMarginRight, rc.top-m_yMarginTop);
  382.     LineTo(hDC, rc.left+m_xMarginLeft,   rc.top-m_yMarginTop);
  383.  
  384.     //CHAPTER7MOD
  385.     /*
  386.      * Go draw the objects on this page.  If the page is not open, we
  387.      * open it anyway.  If it is already open, then opening again will
  388.      * bump it's reference count, so the Close in ineffectual.
  389.      */
  390.     if (FPageGet(m_iPageCur, &pPage, TRUE))
  391.         {
  392.         if (!fPrinter)
  393.             pPage->Draw(hDC, rcPos.left, rcPos.top, fNoColor, fPrinter);
  394.         else
  395.             pPage->Draw(hDC, 0, 0, fNoColor, fPrinter);
  396.  
  397.         pPage->Close(FALSE);
  398.         }
  399.     //End CHAPTER7MOD
  400.  
  401.     SetMapMode(hDC, uMM);
  402.     return;
  403.     }
  404.  
  405.  
  406.  
  407.  
  408.  
  409. /*
  410.  * CPages::UpdateScrollRanges
  411.  *
  412.  * Purpose:
  413.  *  Reset scrollbar ranges (horizontal and vertical) depending on
  414.  *  the window size and the page size.  This function may remove the
  415.  *  scrollbars altogether.
  416.  *
  417.  * Parameters:
  418.  *  None, but set m_cx, m_cy and size m_hWnd before calling.
  419.  *
  420.  * Return Value:
  421.  *  None
  422.  */
  423.  
  424. void CPages::UpdateScrollRanges(void)
  425.     {
  426.     UINT        cxSB;   //Scrollbar width and height.
  427.     UINT        cySB;
  428.     UINT        cx, cy;
  429.     UINT        dx, dy;
  430.     UINT        u;
  431.     int         iMin, iMax;
  432.     RECT        rc;
  433.     BOOL        fHScroll;
  434.     BOOL        fVScroll;
  435.     BOOL        fWasThere;
  436.  
  437.     GetClientRect(m_hWnd, &rc);
  438.  
  439.     cx=rc.right-rc.left;
  440.     cy=rc.bottom-rc.top;
  441.  
  442.     //Convert dimensions of the image in LOMETRIC to pixels.
  443.     SetRect(&rc, (m_cx+m_xMarginLeft+m_xMarginRight+LOMETRIC_BORDER*2)
  444.         , (m_cy+m_yMarginTop+m_yMarginBottom+LOMETRIC_BORDER*2), 0, 0);
  445.  
  446.     RectConvertMappings(&rc, NULL, TRUE);
  447.  
  448.     dx=rc.left;
  449.     dy=-rc.top;
  450.  
  451.     //Assume that both scrollbars will be visible.
  452.     fHScroll=TRUE;
  453.     fVScroll=TRUE;
  454.  
  455.     /*
  456.      * Determine:
  457.      *  1)  Which scrollbars are needed.
  458.      *  2)  How many divisions to give scrollbars so as to
  459.      *      only scroll as little as necessary.
  460.      */
  461.  
  462.     //Scrollbar dimensions in our units.
  463.     cxSB=GetSystemMetrics(SM_CXVSCROLL);
  464.     cySB=GetSystemMetrics(SM_CYHSCROLL);
  465.  
  466.     //Remove horizontal scroll if window >= cxPage+borders
  467.     if (cx >= dx)
  468.         fHScroll=FALSE;
  469.  
  470.  
  471.     /*
  472.      * If we still need a horizontal scroll, see if we need a vertical
  473.      * taking the height of the horizontal scroll into account.
  474.      */
  475.  
  476.     u=fHScroll ? cySB : 0;
  477.  
  478.     if ((cy-u) >= dy)
  479.         fVScroll=FALSE;
  480.  
  481.     //Check to see if adding a vertical scrollbar necessitates a horz now.
  482.     u=fVScroll ? cxSB : 0;
  483.     fHScroll=((cx-u) < dx);
  484.  
  485.     /*
  486.      * Modify cx,cy to reflect the new client area before scaling
  487.      * scrollbars.  We only affect the client size if there is a
  488.      * *change* in scrollbar status:  if the scrollbar was there but
  489.      * is no longer, then add to the client size; if it was not there
  490.      * but now is, then subtract.
  491.      */
  492.  
  493.     //Change cx depending on vertical scrollbar change
  494.     GetScrollRange(m_hWnd, SB_VERT, &iMin, &iMax);
  495.     fWasThere=(0!=iMin || 0!=iMax);
  496.  
  497.     if (fWasThere && !fVScroll)
  498.         cx+=cxSB;
  499.  
  500.     if (!fWasThere && fVScroll)
  501.         cx-=cxSB;
  502.  
  503.     //Change cy depending on horizontal scrollbar change
  504.     GetScrollRange(m_hWnd, SB_HORZ, &iMin, &iMax);
  505.     fWasThere=(0!=iMin || 0!=iMax);
  506.  
  507.     if (fWasThere && !fHScroll)
  508.         cy+=cySB;
  509.  
  510.     if (!fWasThere && fHScroll)
  511.         cy-=cySB;
  512.  
  513.  
  514.     /*
  515.      * Show/Hide the scrollbars if necessary and set the ranges.  The range
  516.      * is the number of units of the page we cannot see.
  517.      */
  518.     if (fHScroll)
  519.         {
  520.         //Convert current scroll position to new range.
  521.         u=GetScrollPos(m_hWnd, SB_HORZ);
  522.  
  523.         if (0!=u)
  524.             {
  525.             GetScrollRange(m_hWnd, SB_HORZ, &iMin, &iMax);
  526.             u=MulDiv(u, (dx-cx), (iMax-iMin));
  527.             }
  528.  
  529.         SetScrollRange(m_hWnd, SB_HORZ, 0, dx-cx, FALSE);
  530.         SetScrollPos(m_hWnd, SB_HORZ, u, TRUE);
  531.         m_xPos=u;
  532.         }
  533.     else
  534.         {
  535.         SetScrollRange(m_hWnd, SB_HORZ, 0, 0, TRUE);
  536.         m_xPos=0;
  537.         }
  538.  
  539.     if (fVScroll)
  540.         {
  541.         //Convert current scroll position to new range.
  542.         u=GetScrollPos(m_hWnd, SB_VERT);
  543.  
  544.         if (0!=u)
  545.             {
  546.             GetScrollRange(m_hWnd, SB_VERT, &iMin, &iMax);
  547.             u=MulDiv(u, (dy-cy), (iMax-iMin));
  548.             }
  549.  
  550.         SetScrollRange(m_hWnd, SB_VERT, 0, dy-cy, FALSE);
  551.         SetScrollPos(m_hWnd, SB_VERT, u, TRUE);
  552.  
  553.         m_yPos=u;
  554.         }
  555.     else
  556.         {
  557.         SetScrollRange(m_hWnd, SB_VERT, 0, 0, TRUE);
  558.         m_yPos=0;
  559.         }
  560.  
  561.     //Repaint to insure that changes to m_xPos and m_yPos are reflected
  562.     InvalidateRect(m_hWnd, NULL, TRUE);
  563.  
  564.     return;
  565.     }
  566.  
  567.  
  568.  
  569.  
  570.  
  571.  
  572.  
  573.  
  574.  
  575. /*
  576.  * CPages::Print
  577.  *
  578.  * Purpose:
  579.  *  Prints a specified range of pages to a given hDC.  Repeats for
  580.  *  a given number of copies.
  581.  *
  582.  * Parameters:
  583.  *  hDC             HDC to which we print.
  584.  *  pszDoc          LPSTR providing the document name.
  585.  *  dwFlags         DWORD flags from PrintDlg
  586.  *  iPageStart      UINT starting page index (one based)
  587.  *  iPageEnd        UINT ending page index (one based).  Includes this page.
  588.  *  cCopies         UINT number of copies to print.  If PD_COLLATE in
  589.  *                  dwFlags is set, we print multiple copies of each page
  590.  *                  as we cycle through.  Otherwise we cycle multiple times.
  591.  *
  592.  * Return Value:
  593.  *  None
  594.  */
  595.  
  596. BOOL CPages::Print(HDC hDC, LPSTR pszDoc, DWORD dwFlags, UINT iPageStart
  597.     , UINT iPageEnd, UINT cCopies)
  598.     {
  599.     BOOL        fError=FALSE;
  600.     int         iPage, iPageInc;
  601.     int         iUserPage, cPages;
  602.     UINT        iRepeat, cRepeat;
  603.     UINT        iCycle, cCycles;
  604.     UINT        iPageHold=m_iPageCur;
  605.     HWND        hWndT, hWndTop=NULL;
  606.     DLGPROC     pfnDlg;
  607.     ABORTPROC   pfnAbort;
  608.     DOCINFO     di;
  609.  
  610.     //Validate hDC and page ranges
  611.     if (NULL==hDC)
  612.         return FALSE;
  613.  
  614.     if ((PD_PAGENUMS & dwFlags))
  615.         {
  616.         if (-1==iPageStart)
  617.             iPageStart=0;
  618.  
  619.         if (-1==iPageEnd)
  620.             iPageEnd=m_cPages-1;
  621.         }
  622.     else //Can't test PD_ALLPAGES with & since it's defined as 0L
  623.         {
  624.         iPageStart=0;
  625.         iPageEnd=m_cPages-1;
  626.         }
  627.  
  628.     //Arrage number of cycles and repeats depending on cCopies and flags.
  629.     if (PD_COLLATE & dwFlags)
  630.         {
  631.         cCycles=cCopies;
  632.         cRepeat=1;
  633.         }
  634.     else
  635.         {
  636.         cCycles=1;
  637.         cRepeat=cCopies;
  638.         }
  639.  
  640.     //Disable the top window to prevent reentrancy while printing.
  641.     hWndT=m_hWnd;
  642.  
  643.     while (NULL!=hWndT)
  644.         {
  645.         hWndTop=hWndT;
  646.         hWndT=GetParent(hWndT);
  647.         }
  648.  
  649.     EnableWindow(hWndTop, FALSE);
  650.  
  651.     pfnAbort=(ABORTPROC)MakeProcInstance((FARPROC)AbortProc, m_hInst);
  652.     SetAbortProc(hDC, pfnAbort);
  653.  
  654.     g_fCancelPrint=FALSE;
  655.  
  656.     //If these don't work then we'll just live without a dialog.
  657.     pfnDlg=(DLGPROC)MakeProcInstance((FARPROC)PrintDlgProc, m_hInst);
  658.     g_hDlgPrint=CreateDialog(m_hInst, MAKEINTRESOURCE(IDD_PRINTING)
  659.         , hWndTop, pfnDlg);
  660.  
  661.  
  662.     //Increment for either direction.
  663.     iPageInc=(iPageStart > iPageEnd) ? -1 : 1;
  664.  
  665.     //Initial entries in dialog box.
  666.     cPages=1+((int)(iPageEnd-iPageStart)*iPageInc);
  667.  
  668.     SendMessage(g_hDlgPrint, PRINTM_PAGEUPDATE, 1, (LPARAM)cPages);
  669.     SendMessage(g_hDlgPrint, PRINTM_COPYUPDATE, 1, (LPARAM)cRepeat);
  670.  
  671.     di.cbSize=sizeof(DOCINFO);
  672.     di.lpszDocName=pszDoc;
  673.     di.lpszOutput=NULL;
  674.  
  675.     if (StartDoc(hDC, &di) > 0)
  676.         {
  677.         /*
  678.          * Iterate over the pages, repeating each page depending on
  679.          * the copies we want and if we have collate enabled.
  680.          */
  681.  
  682.         for (iCycle=1; iCycle <= cCycles; iCycle++)
  683.             {
  684.             if (PD_COLLATE & dwFlags)
  685.                 SendMessage(g_hDlgPrint, PRINTM_COPYUPDATE, iCycle, (LPARAM)cCycles);
  686.  
  687.             //iPageInc controls direction; end of loop controls termination.
  688.             for (iPage=iPageStart; ; iPage+=iPageInc)
  689.                 {
  690.                 iUserPage=1+((iPage-(int)iPageStart)*iPageInc);
  691.  
  692.                 SendMessage(g_hDlgPrint, PRINTM_PAGEUPDATE
  693.                     , iUserPage, (LPARAM)cPages);
  694.  
  695.                 m_iPageCur=iPage;   //We restore this later.
  696.  
  697.                 for (iRepeat=1; iRepeat <= cRepeat; iRepeat++)
  698.                     {
  699.                     if (!(PD_COLLATE & dwFlags))
  700.                         {
  701.                         SendMessage(g_hDlgPrint, PRINTM_COPYUPDATE
  702.                             , iRepeat, (LPARAM)cRepeat);
  703.                         }
  704.  
  705.                     StartPage(hDC);
  706.                     Draw(hDC, TRUE, TRUE);
  707.  
  708.                     if (EndPage(hDC) < 0)
  709.                         fError=TRUE;
  710.  
  711.                     if (fError || g_fCancelPrint)
  712.                         break;
  713.                     }
  714.  
  715.                 if (fError || g_fCancelPrint)
  716.                     break;
  717.  
  718.                 //If we just printed the last page, time to quit.
  719.                 if (iPage==(int)iPageEnd)
  720.                     break;
  721.                 }
  722.  
  723.             if (fError || g_fCancelPrint)
  724.                 break;
  725.             }
  726.  
  727.         if (!fError)
  728.             EndDoc(hDC);
  729.         else
  730.             AbortDoc(hDC);
  731.         }
  732.     else
  733.         fError=TRUE;
  734.  
  735.     //Set the page back to what it was before all this started.
  736.     m_iPageCur=iPageHold;
  737.  
  738.     DestroyWindow(g_hDlgPrint);
  739.     SetActiveWindow(hWndTop);
  740.  
  741.     FreeProcInstance((FARPROC)pfnDlg);
  742.     FreeProcInstance((FARPROC)pfnAbort);
  743.     EnableWindow(hWndTop, TRUE);
  744.     DeleteDC(hDC);
  745.  
  746.     return !fError;
  747.     }
  748.  
  749.  
  750.  
  751.  
  752.  
  753.  
  754. /*
  755.  * AbortProc
  756.  *
  757.  * Purpose:
  758.  *  Abort procedure for printing the pages.
  759.  *
  760.  * Parameters:
  761.  *  hDC             HDC on which printing is happening.
  762.  *  iErr            int error code.
  763.  *
  764.  * Return Value:
  765.  *  BOOL            TRUE to continue the print job, FALSE otherwise.
  766.  */
  767.  
  768. BOOL __export FAR PASCAL AbortProc(HDC hDC, int iErr)
  769.     {
  770.     MSG     msg;
  771.  
  772.     while (!g_fCancelPrint && PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  773.         {
  774.         if (NULL==g_hDlgPrint || !IsDialogMessage(g_hDlgPrint, &msg))
  775.             {
  776.             TranslateMessage(&msg);
  777.             DispatchMessage(&msg);
  778.             }
  779.         }
  780.  
  781.     return !g_fCancelPrint;
  782.     }
  783.  
  784.  
  785.  
  786.  
  787. /*
  788.  * PrintDlgProc
  789.  *
  790.  * Purpose:
  791.  *  Modeless dialog procedure for the dialog displayed while Patron
  792.  *  is printing pages.
  793.  */
  794.  
  795. BOOL __export FAR PASCAL PrintDlgProc(HWND hDlg, UINT iMsg
  796.     , WPARAM wParam, LPARAM lParam)
  797.     {
  798.     char            szFormat[40];
  799.     char            szOutput[80];
  800.  
  801.     switch (iMsg)
  802.         {
  803.         case WM_INITDIALOG:
  804.             EnableMenuItem(GetSystemMenu(hDlg, FALSE), SC_CLOSE, MF_GRAYED);
  805.             return TRUE;
  806.  
  807.         case WM_COMMAND:
  808.             //Cancel button was pressed.
  809.             g_fCancelPrint=TRUE;
  810.             ShowWindow(hDlg, SW_HIDE);
  811.             return TRUE;
  812.  
  813.         case PRINTM_PAGEUPDATE:
  814.             GetDlgItemText(hDlg, ID_PAGESTRING, szFormat, sizeof(szFormat));
  815.             wsprintf(szOutput, szFormat, (UINT)wParam, (UINT)lParam);
  816.             SetDlgItemText(hDlg, ID_CURRENTPAGE, szOutput);
  817.             return TRUE;
  818.  
  819.         case PRINTM_COPYUPDATE:
  820.             GetDlgItemText(hDlg, ID_COPYSTRING, szFormat, sizeof(szFormat));
  821.             wsprintf(szOutput, szFormat, (UINT)wParam, (UINT)lParam);
  822.             SetDlgItemText(hDlg, ID_CURRENTCOPY, szOutput);
  823.             return TRUE;
  824.         }
  825.  
  826.     return FALSE;
  827.     }
  828.